#pragma once
#include <chrono>
#include <string>
#include <vector>
#include <algorithm>
#include <filesystem>
#include <unordered_map>
#include <map>

using namespace std;

namespace utils
{
    namespace str
    {
        /**
        * 字符串按照指定分隔符分割为数组
        * @param str 传入要分割的字符串
        * @param delimiter 分隔符
        * @return 分割好的数组
        */
        static std::vector<std::string> split(const std::string& str, const std::string& delimiter) {
            std::vector<std::string> tokens;
            size_t prev = 0, pos = 0;

            // 检查分隔符是否为空
            if (delimiter.empty()) {
                tokens.push_back(str);
                return tokens;
            }

            // 使用find查找分隔符，并使用substr提取子字符串
            while ((pos = str.find(delimiter, prev)) != std::string::npos) {
                tokens.push_back(str.substr(prev, pos - prev));
                prev = pos + delimiter.length();
            }

            // 将最后一个子字符串添加到向量中
            tokens.push_back(str.substr(prev, str.length() - prev));

            return tokens;
        }

        /**
         * 字符串按照指定分隔符分割为数组
         * @param str 传入要分割的字符串
         * @param delimiter 分隔符
         * @param max_split 最大分割次数
         * @return
         */
        static std::vector<std::string> split(std::string& str, const std::string& delimiter, signed int max_split) {
            std::vector<std::string> tokens;
            size_t prev = 0, pos = 0;

            // 检查分隔符是否为空
            if (delimiter.empty()) {
                tokens.push_back(str);
                return tokens;
            }

            // 使用find查找分隔符，并使用substr提取子字符串
            while ((pos = str.find(delimiter, prev)) != std::string::npos && max_split > 0) {
                tokens.push_back(str.substr(prev, pos - prev));
                prev = pos + delimiter.length();
                max_split--;
            }

            // 将最后一个子字符串添加到向量中
            tokens.push_back(str.substr(prev, str.length() - prev));

            return tokens;
        }

        /**
         * 字符串替换字符
         * @param str 传入要替换的字符串
         * @param old_str 替换前的子串
         * @param new_str 替换后的子串
         */
        static void replaceSelf(string& str, const string& old_str, const string& new_str) {
            size_t pos = str.find(old_str);
            while (pos != string::npos) {
                str.replace(pos, old_str.size(), new_str);
                pos = str.find(old_str, pos + new_str.size());
            }
        }

        /**
         * 字符串替换
         * @param str 传入要替换的字符串
         * @param old_str 替换前的子串
         * @param new_str 替换后的子串
         * @return 结果的字符串
         */
        [[nodiscard]]
        static string replace(const string& str, const string& old_str, const string& new_str) {
            string result = str;
            size_t pos = result.find(old_str);
            while (pos != string::npos) {
                result.replace(pos, old_str.size(), new_str);
                pos = result.find(old_str, pos + new_str.size());
            }
            return result;
        }

        /**
         * 字符串去除首尾空格
         * @param str 传入字符串
         * @return 传出字符串
         */
        static string& trim(string& str) {
            const size_t first = str.find_first_not_of(' ');
            if (std::string::npos == first) {
                return str;
            }
            const size_t last = str.find_last_not_of(' ');
            str = str.substr(first, (last - first + 1));
            return str;
        }

        /**
         * 解析http请求体
         * @param params 待解析的http请求体
         * @return 解析完成的数组
         */
        static unordered_map<string, string> splitHttpParams(const string& params) {
            unordered_map<string, string> params_map;
            istringstream iss(params);
            string param;

            while (getline(iss, param, '&')) {
                const size_t pos = param.find('=');
                if (pos != string::npos) {
                    const string key = param.substr(0, pos);
                    const string value = param.substr(pos + 1);
                    params_map[key] = value;
                }
            }
            return params_map;
        };
    }

    namespace time
    {
        /**
         * 格式化时间戳，默认为当前时间
         * @param seconds 传入的时间戳，秒数
         * @param format 格式化选项
         * @return 格式化结果
         */
        static string formatTime(const string& format,
                                 const time_t seconds = chrono::system_clock::to_time_t(chrono::system_clock::now())) {
            tm gm_tm{};
            gmtime_s(&gm_tm, &seconds);

            ostringstream oss;
            oss << put_time(&gm_tm, format.c_str()); //%w 是数字显示星期几，%A 是英文Friday这种
            return oss.str();
        }

        /**
         * 时间戳秒数，距离1970年1月1日00:00:00 UTC
         * @return 当前时间戳秒数
         */
        static int nowTimeStamp() {
            return static_cast<int>(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()));
        }

        /**
         * 格式化文件系统时间
         * @param file_time 文件系统时间
         * @param format 格式化选项
         * @return 格式化后的时间
         */
        static string fileTime(const filesystem::file_time_type file_time, const string& format) {
            //11644473600 是文件系统和utc时间的差值，28800是utc 和 utc+8的差值
            const auto systemTime = chrono::duration_cast<chrono::seconds>(file_time.time_since_epoch()).count() -
                11644473600 +
                28800;

            tm gm_tm{};
            gmtime_s(&gm_tm, &systemTime);

            // 将time_t类型转换为tm结构体
            ostringstream oss;
            oss << put_time(&gm_tm, format.c_str());
            return oss.str();
        }


        /**
         * 计算函数执行耗时
         * @tparam Func 函数地址
         * @param f 函数名
         * @return 函数执行耗时，单位为毫秒
         */
        template <typename Func>
        static long long measureTime(Func f) {
            const auto start = std::chrono::high_resolution_clock::now();
            //执行函数
            f();
            const auto end = std::chrono::high_resolution_clock::now();
            return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
        }
    }

    namespace stl
    {
        /**
         * 查找容器内元素的下标
         * @tparam Container STL容器类型
         * @tparam T 要查找的元素类型
         * @param container STL容器
         * @param element 要查找的元素
         * @return 所在的下标
         */
        template <typename Container, typename T>
        [[nodiscard]]
        // typename Container::size_type findIndex(const Container& container, const T& element) {
        int findIndex(const Container& container, const T& element) {
            auto it = std::find(container.begin(), container.end(), element);
            if (it != container.end()) {
                return static_cast<int>(std::distance(container.begin(), it));
            }
            // return static_cast<typename Container::size_type>(-1);
            return -1;
        }
    }

}


// %a：星期的简写名称（例如，"Mon"，"Tue"）。
// %A：星期的全称（例如，"Monday"，"Tuesday"）。
// %b：月份的简写名称（例如，"Jan"，"Feb"）。
// %B：月份的全称（例如，"January"，"February"）。
// %c：本地日期和时间的表示（例如，"Mon Jan 02 03:04:05 1993"）。
// %C：年份的前两位数字（例如，"19" 对应于 1993 年）。
// %d：月份中的一天（01 到 31）。
// %D：日期（%m/%d/%y）。
// %e：月份中的一天（1 到 31），如果需要，前面有一个空格。
// %F：ISO 8601 日期格式（%Y-%m-%d）。
// %G：ISO 8601 年份（四位数）。
// %g：ISO 8601 年份（两位数）。
// %H：小时（00 到 23）。
// %I：小时（01 到 12）。
// %j：一年中的第几天（001 到 366）。
// %m：月份（01 到 12）。
// %M：分钟（00 到 59）。
// %n：换行符。
// %p：本地的 AM 或 PM 表示。
// %R：24 小时制的时间（%H:%M）。
// %r：12 小时制的时间（%I:%M:%S %p）。
// %S：秒（00 到 59）。
// %t：水平制表符。
// %T：24 小时制的时间（%H:%M:%S）。
// %u：ISO 8601 星期数（1 到 7，1 表示星期一）。
// %U：一年中的第几周，星期日作为一周的第一天（00 到 53）。
// %V：一年中的第几周，星期一作为一周的第一天（01 到 53），与 %G 和 %g 一起使用。
// %w：星期中的一天（0 到 6，0 表示星期日）。
// %W：一年中的第几周，星期一作为一周的第一天（00 到 53）。
// %x：本地日期的表示（例如，"02/03/93"）。
// %X：本地时间的表示（例如，"03:04:05"）。
// %y：年份的后两位数字（例如，"93" 对应于 1993 年）。
// %Y：年份（例如，"1993"）。
// %z：UTC 的偏移量（例如，"-0500" 或 "+0600"）。
// %Z：时区名称（例如，"EST" 或 "MDT"）。
